/*-------------------------------------------------------------------------------------
 * Class:   Table2GB2UCS2
 * Author:  xiexudong
 * Version: 1.0
 * Date:
 * Copyright:2009 xiexudong. All Rights Reserved. 
 * Dcecription: 
 --------------------------------------------------------------------------------------*/

/**                         Important Edit History                                             *
 ** ------------------------------------------------------------------------------------*
 ** DATE           NAME             DESCRIPTION                                          *
 ** 4/2009       xudong.xie         Creat
 ---------------------------------------------------------------------------------------*/

/*-----------------------------------------------------------------------------------------------------
 Package 
 ------------------------------------------------------------------------------------------------------*/
package com.language.gb;

/*-----------------------------------------------------------------------------------------------------
 Import LIB
 ------------------------------------------------------------------------------------------------------*/

//import java.util.*;
//import java.lang.Object;

//GB2312 To UCS2 Table  
//由于编译问题，把改码表拆开成三部分了
//TableGB2UCS2 + Table2GB2UCS2+ Table3GB2UCS2

public class GbEnDecode {

    public static final int MAX_CONVERT_GB_BUF_LEN = 0xFFF;

    public static final int GB_OFFSET_NUMBER = 94; // the number of one GB zone.
    public static final int GB_MIN_ZONE = 0xA0; // min value of the zone number
    // of GB code
    public static final int GB_MAX_ZONE = 0xF8; // max value of the zone number
    // of GB code
    public static final int GB_MIN_OFFSET = 0xA1; // min value of the offset
    // number of GB code
    public static final int GB_MAX_OFFSET = 0xFF; // max value of the offset
    // number of GB code
    public static final int MAX_OFFSET_IN_TABLE = 8272; // the max offset of the
    // conversion table.

    public static final int MAX_OFFSET_IN_TABLE1 = 8272; // the max offset of
    // the conversion
    // table.
    public static final int MAX_OFFSET_IN_TABLE2 = 8272; // the max offset of
    // the conversion
    // table.

    /*
     * /*************************************************************************
     * ***
     */
    // Description : convert an GB2312 string to UCS2 string.
    // Global resource dependence : none
    // Author:
    // Note:
    /*****************************************************************************/

    public static String GB2312ToUCS2(byte[] gb_buf, int len) {

        // char[] ucs2_char_array = new char[1] ;
        StringBuffer str_buf = new StringBuffer();

        int tmp_gb = 0;
        // int count = 0;

        int index = 0;

        int gb_len = len;

        // Trace.println("*****GB2312ToUCS2: GB_MIN_ZONE = "+GB_MIN_ZONE+
        // ";  GB_MAX_ZONE = " + GB_MAX_ZONE);

        while ((gb_len > 0) && (gb_len < MAX_CONVERT_GB_BUF_LEN)) {
            gb_len--;
            // count += 2;
            // System.out.println("====="+count);
            tmp_gb = gb_buf[index++] & 0xFF;

            // Trace.println("*****GB2312ToUCS2: index = "+index+ "tmp_gb = " +
            // (int)tmp_gb);

            if (tmp_gb < 0x80) // An ASCII
            {

                str_buf.append((char) (tmp_gb & 0x00FF));

                // Trace.println("GB2312ToUCS2: tmp_gb,  " + tmp_gb);

            } else if ((tmp_gb >= GB_MIN_ZONE) && (tmp_gb < GB_MAX_ZONE)) {
                int offset = (int) (gb_buf[index++]) & 0xFF;

                // Trace.println("-------GB2312ToUCS2: offset 1  " + offset);

                gb_len--;

                if ((offset >= GB_MIN_OFFSET) && (offset < GB_MAX_OFFSET)) {
                    char ucs2_code = 0;

                    offset = (offset - GB_MIN_OFFSET) + (tmp_gb - GB_MIN_ZONE)
                            * GB_OFFSET_NUMBER;

                    // Trace.println("GB2312ToUCS2: offset 2 " + offset);

                    if (offset < TableGB2UCS2.value.length) {
                        ucs2_code = TableGB2UCS2.value[offset];
                    } else if (offset < (TableGB2UCS2.value.length + Table2GB2UCS2.value.length)) // 在第二张表中
                    {
                        ucs2_code = Table2GB2UCS2.value[offset
                                - TableGB2UCS2.value.length];
                    } else if (offset < (+TableGB2UCS2.value.length
                            + Table2GB2UCS2.value.length + Table3GB2UCS2.value.length)) {

                        ucs2_code = Table3GB2UCS2.value[offset
                                - TableGB2UCS2.value.length
                                - Table2GB2UCS2.value.length];
                    } else {
                        ucs2_code = 0x3000;
                    }

                    str_buf.append(ucs2_code);

                    // Trace.println("GB2312ToUCS2:ucs2_code =  " + ucs2_code);
                    // Trace.println("GB2312ToUCS2: ucs2_code = " +
                    // (int)ucs2_code);

                } else {
                    str_buf.append((char) 0x3000);

                }
            } else {
                // An invalidate code.
                // An invalidate code.

                str_buf.append((char) 0x3000);

                index++;
                gb_len--;
            }
        }

        return new String(str_buf);
    }

    public static byte[] UCS2ToGB2312(String str) {
        int len = str.length();

        return UCS2ToGB2312(str.toCharArray(), len);
        /*
         * int ucs2_length = str.length(); int gb_len = 0;
         *
         * byte[] gb_buf = new byte[ucs2_length*2];
         *
         * int offset = 0; char ucs2 = 0; char gb2312 = 0xA1A1; int gb_length =
         * 0;
         *
         * int ucs2_index = 0;
         *
         * while(ucs2_index < ucs2_length) { gb2312 = 0xA1A1;
         *
         * ucs2 = str.charAt(ucs2_index);
         *
         * if( 0x80 > ucs2 ) { gb_buf[gb_length] = (byte)(ucs2 & 0xFF);
         * gb_length++; } else {
         *
         * //Trace.println("UCS2ToGB2312: ucs2 = " + ChartoByteStr(ucs2));
         *
         * if( (0x4E00 <= ucs2) && (0xA000 > ucs2) ) { offset =
         * TableIndexUCS2ToGB.GetUCSOffset( ucs2);//offset = GetUCSOffset( ucs2
         * );
         *
         * ////Trace.println("*********UCS2ToGB2312: offset = " +offset); if
         * (offset >= 0) {
         *
         * if(offset < TableUCS2ToGB.value.length) { gb2312 =
         * TableUCS2ToGB.value[ offset ]; } else if(offset <
         * TableUCS2ToGBPart2.value.length + TableUCS2ToGB.value.length) {
         * gb2312 = TableUCS2ToGBPart2.value[ offset -
         * TableUCS2ToGB.value.length ]; } else if(offset <
         * TableUCS2ToGBPart3.value.length + TableUCS2ToGBPart2.value.length +
         * TableUCS2ToGB.value.length ) { gb2312 = TableUCS2ToGBPart3.value[
         * offset - TableUCS2ToGB.value.length
         * -TableUCS2ToGBPart2.value.length]; } else {
         *
         * }
         *
         * } } else { // Is chinese symbol ? try search another table
         *
         * for( offset = 0; offset < 94 * 16; offset++ ) {
         *
         * //if(offset < TableGB2UCS2.value.length) { if( ucs2 ==
         * TableGB2UCS2.value[ offset ] ) { gb2312 = (char)((offset / 94 +
         * 0xA0)&0xFFFF); gb2312 = (char)(((gb2312 << 8) + (offset % 94 +
         * 0xA1))& 0xFFFF); break; } } } }
         *
         * gb_buf[gb_length++] = (byte)(( gb2312 >> 8) & 0xFF);
         * gb_buf[gb_length++] =(byte)( gb2312 & 0xFF ); } ucs2_index++; }
         *
         * if(gb_length < gb_buf.length) //生成刚好存放数据的新数组 { byte[] ret_gb_buf =
         * new byte[gb_length]; for( int i =0; i< gb_length; i++) {
         * ret_gb_buf[i] = gb_buf[i]; }
         *
         * return ret_gb_buf; } else { return gb_buf; }
         */

    }

    /*****************************************************************************/
    // Description : convert an UCS2 string to GB2312 string.
    // Global resource dependence : none
    // Author:
    // Note:
    /*****************************************************************************/
    public static byte[] UCS2ToGB2312( // return the length of gb2312_ptr
                                       char[] ucs_char_array, // the ucs2 stringcode that need to be
                                       // converted.
                                       int length // the unicode length
    ) {

        int ucs2_length = ucs_char_array.length;

        // int gb_len = 0;
        byte[] gb_buf = new byte[ucs2_length * 2];

        int offset = 0;
        char ucs2 = 0;
        char gb2312 = 0xA1A1;
        int gb_length = 0;

        int ucs2_index = 0;

        while (ucs2_index < ucs_char_array.length) {
            gb2312 = 0xA1A1;

            ucs2 = ucs_char_array[ucs2_index];

            if (0x80 > ucs2) {
                // can be convert to ASCII char
                gb_buf[gb_length] = (byte) (ucs2 & 0xFF);
                gb_length++;
            } else {

                // Trace.println("UCS2ToGB2312: ucs2 = " + ChartoByteStr(ucs2));

                if ((0x4E00 <= ucs2) && (0xA000 > ucs2)) {
                    offset = TableIndexUCS2ToGB.GetUCSOffset(ucs2);// offset =
                    // GetUCSOffset(
                    // ucs2 );

                    // //Trace.println("*********UCS2ToGB2312: offset = "
                    // +offset);
                    if (offset >= 0) {

                        if (offset < TableUCS2ToGB.value.length) {
                            gb2312 = TableUCS2ToGB.value[offset];
                        } else if (offset < TableUCS2ToGBPart2.value.length
                                + TableUCS2ToGB.value.length) {
                            gb2312 = TableUCS2ToGBPart2.value[offset
                                    - TableUCS2ToGB.value.length];
                        } else if (offset < TableUCS2ToGBPart3.value.length
                                + TableUCS2ToGBPart2.value.length
                                + TableUCS2ToGB.value.length) {
                            gb2312 = TableUCS2ToGBPart3.value[offset
                                    - TableUCS2ToGB.value.length
                                    - TableUCS2ToGBPart2.value.length];
                        } else {

                        }

                    }
                } else {
                    // Is chinese symbol ? try search another table

                    for (offset = 0; offset < 94 * 16; offset++) {

                        // if(offset < TableGB2UCS2.value.length)
                        {
                            if (ucs2 == TableGB2UCS2.value[offset]) {
                                gb2312 = (char) ((offset / 94 + 0xA0) & 0xFFFF);
                                gb2312 = (char) (((gb2312 << 8) + (offset % 94 + 0xA1)) & 0xFFFF);
                                break;
                            }
                        }
                    }
                }

                gb_buf[gb_length++] = (byte) ((gb2312 >> 8) & 0xFF);
                gb_buf[gb_length++] = (byte) (gb2312 & 0xFF);

            }

            ucs2_index++;
        }

        if (gb_length < gb_buf.length) // 生成刚好存放数据的新数组
        {
            byte[] ret_gb_buf = new byte[gb_length];
            for (int i = 0; i < gb_length; i++) {
                ret_gb_buf[i] = gb_buf[i];
            }

            return ret_gb_buf;
        } else {
            return gb_buf;
        }

    }
}